home *** CD-ROM | disk | FTP | other *** search
- ; map8_quick.s
- ; MACHINE: RISC OS
- ; LANGUAGE: OBJASM assembler
- ; AUTHOR: Cy Booker, cy@cheepnis.demon.co.uk
- ; LICENSE: FreeWare, Copyright (c) Cy Booker 1996
- ; PURPOSE: Given an arbitary 48-bit colour, what is the closest 8-bit colour number?
- ; assuming the default 256 colour palette
- ;
- ; Note the algorithm used is based on the one inside Acorns' ChangeFSI
- ; but modified slightly by me to be faster and more accurate
- ;
- ; ChangeFSI's algorithm is the same as the one posted to UseNet
- ;
- ; Message-ID: <12463@acorn.co.uk>
- ; Date: 30 Jan 92 12:20:23 GMT
- ; From: RWilson@acorn.co.uk
- ; Subject: How to find the closest colour out of the RISC OS 256
- ;
- ; And so I hereby acknowledge that I'm using their spiffy code
- ;
- ; in middle we have |intensity-difference| <-- 0x3fff
- ; so |i|^2 <= 0x0fff8001
- ; and so |d|^2 <= 3.|i|^2 <= 0x2ffe8003
- ; so total scale must be < 2^32/(|d|^2) , ie < ~5
- ; but this does not leave enough accuracy really, so we shift by a bit
- ;
- ; the weights we want are:
- ; Red * 0.212671 * 14 ~= 3 / 4 ~= 0x0.c
- ; Green * 0.715160 * 14 ~= 10 / 4 ~= 0x2.8
- ; Blue * 0.072169 * 14 ~= 1 / 4 ~= 0x0.4
- ;
- ; note we will divide by 2 to ensure total < 2^32
- ; (ie 0x3fff*0x3fff*3*14/2 < 2^32)
- ;
-
-
- GET OS:Hdr.os
-
- ;
-
- EXPORT map_scaled_rgb_to_8bpp_colour_number_quick
-
- AREA |ARM$$code|, CODE, READONLY
-
- ROUT
-
- ;
- ; In R0 -> structure
- ; structure[3] = pointer to array of {red, green, blue} for default wimp palette
- ; structure[4] = number of entries in array (== 256)
- ; R1 = red nominally [0, 0xffff], but clipped as necessary
- ; R2 = green nominally [0, 0xffff], but clipped as necessary
- ; R3 = blue nominally [0, 0xffff], but clipped as necessary
- ; Out R0 <-- palette entry %BGgRbrTt (bits 8-31 are zero)
- ; structure[0] = error in approximating red intensity
- ; structure[1] = error in approximating green intensity
- ; structure[2] = error in approximating blue intensity
- ;
-
- ROUT
-
- map_scaled_rgb_to_8bpp_colour_number_quick
-
- str RN a1
- red RN a2
- grn RN a3
- blu RN a4
- tint RN v1
- dmin RN v2
- dist RN v3
- colour RN v4
- best RN v5
- mtint RN v6
- x RN ip
- y RN lr
-
- dr RN tint
- dg RN dmin
- db RN dist
-
- bits * 16 ; the inline weighting functions assume bits <= 16
-
- STMFD sp!, {v1-v6, lr}
- MOV lr, #1 << bits
- CMP red, lr ; ensure in range [0, 0xffff]
- MOVHS red, #0
- SUBGE red, lr, #1
- CMP grn, lr
- MOVHS grn, #0
- SUBGE grn, lr, #1
- CMP blu, lr
- MOVHS blu, #0
- SUBGE blu, lr, #1
- ;
- MOV dmin, #&ffffffff
- MOV tint, #&30 << 23
- 0
- RSB mtint, tint, #&20 << 23
-
- SUB y, blu, blu, LSR #4 ; y ~= blu * 16 / 17
- ADDS x, mtint, y, LSL #31 - bits
- MOVVSS x, #&c0 << 23
- MOVMI x, #0
- AND x, x, #&c0 << 23 ; %0Bb0 0000 0000 0000 0000 0000 0000 0000
- ADD x, x, tint ; %0BbT t000 0000 0000 0000 0000 0000 0000
- ADD colour, x, x, LSR #4 ; colour = blu << 23
- [ bits > 8
- ADD x, colour, colour, LSR #8 ; %0BbT tBbT tBbT tBbT t000 0000 0000 0000
- [ bits > 16
- ADD x, x, x, LSR #16 ; %0BbT tBbT tBbT tBbT tBbT tBbT tBbT tBbT
- ]
- SUBS y, blu, x, LSR #31 - bits ; bug in changefsi here!
- |
- SUBS y, blu, colour, LSR #31 - bits
- ]
- RSBLT y, y, #0 ; speeds up MUL instruction
-
- MUL dist, y, y ; dist = blu * 0x1.0
-
- SUB y, grn, grn, LSR #4
- ADDS x, mtint, y, LSL #31 - bits
- MOVVSS x, #&c0 << 23
- MOVMI x, #0
- AND x, x, #&c0 << 23
- ADD x, tint, x
- ADD x, x, x, LSR #4
- ORR colour, colour, x, LSR #8 ; colour |= grn << 15
- [ bits > 8
- ADD x, x, x, LSR #8
- [ bits > 16
- ADD x, x, x, LSR #16
- ]
- ]
- SUBS y, grn, x, LSR #31 - bits
- RSBLT y, y, #0
-
- MUL x, y, y
- MOV x, x, LSL #1
- ADD dist, x, dist, LSR #2 ; dist = blu * 0x0.4 + grn * 0x2.0
- ADD dist, dist, x, LSR #3 ; dist = blu * 0x0.4 + grn * 0x2.8
-
- SUB y, red, red, LSR #4
- ADDS x, mtint, y, LSL #31 - bits
- MOVVSS x, #&c0 << 23
- MOVMI x, #0
- AND x, x, #&c0 << 23
- ADD x, tint, x
- ADD x, x, x, LSR #4
- ORR colour, colour, x, LSR #16 ; colour |= red << 7
- [ bits > 8
- ADD x, x, x, LSR #8
- [ bits > 16
- ADD x, x, x, LSR #16
- ]
- ]
- SUBS y, red, x, LSR #31 - bits
- RSBLT y, y, #0
-
- MULNE x, y, y
- ADDNE dist, dist, x, LSR #2 ; dist = blu * 0x0.4 + grn * 0x2.8 + red * 0x0.4
- ADDNE dist, dist, x, LSR #1 ; dist = blu * 0x0.4 + grn * 0x2.8 + red * 0x0.c
-
- CMP dist, dmin
-